from Pyro.protocol import DefaultConnValidator
import Pyro.constants
import hmac, hashlib
import const, db, logger, config
                

#  Passwords are protected using md5 so they are not stored in plaintext.
#  The actual identification check is done using a hmac-md5 secure hash.
class UserLoginConnValidator(DefaultConnValidator):
    logger = logger.setup_logging("UserLoginConnValidator", config.LOG_LOGINS)    
    
    def acceptIdentification(self, daemon, connection, token, challenge):
        # extract tuple (login, processed password) from token as returned by createAuthToken
        # processed password is a hmac hash from the server's challenge string and the password itself.
        login, processedpassword = token.split(':', 1)
        db_man = db.DbManager()
        db_man.connect(const.DB_NAME)
        knownpasswdhash = db_man.get_password(login)
        # Check if the username/password is valid.
        if knownpasswdhash:
            # Known passwords are stored as ascii hash, but the auth token contains a binary hash.
            # So we need to convert our ascii hash to binary to be able to validate.
            # verify that credentials match            
            knownpasswdhash = knownpasswdhash.decode("hex")
            if hmac.new(challenge,knownpasswdhash).digest() == processedpassword:                
                msg = "Access granted to user:'" + login + "' from client " + str(connection.addr)
                connection.authenticated = login # store for later reference by Pyro object
                self.logger.debug(msg)
                return(1,0)
        msg = "Denied access to user:'" + login + "' from client " + str(connection.addr)
        db_man.close()
        self.logger.debug(msg)
        return (0, Pyro.constants.DENIED_SECURITY)    
    
    def createAuthToken(self, authid, challenge, peeraddr, URI, daemon):
        # authid is what mungeIdent returned, a tuple (login, hash-of-password)
        # we return a secure auth token based on the server challenge string.
        return "%s:%s" % (authid[0], hmac.new(challenge,authid[1]).digest())
    
    def mungeIdent(self, ident):
        # ident is tuple (login, password), the client sets this.
        # we don't like to store plaintext passwords so store the md5 hash instead.
        return (ident[0], hashlib.md5(ident[1]).digest()) #@UndefinedVariable
    
